# -*- coding: UTF-8 -*-
import re
import os
import datetime
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from socket import gaierror, error
import poplib
from email.parser import Parser
from email.header import decode_header
from email.utils import parseaddr
from pyLib.LogManage import LOG
from pyLib.YamlManage import YamlReader
from tools.handle_path import config_path

SMTP_SERVER = "smtp.exmail.qq.com"
POP3_SERVER = "pop.exmail.qq.com"
# SENDER = ("leihong.song@proinnova.com.cn", "Dell2020")
template_host = YamlReader(file_path=os.path.join(config_path, "params_config.yaml")).get("email_info")
SENDER = (template_host.get("user"), template_host.get("pwd"))


class Email:
    def __init__(self, sender=SENDER, receiver=None, cc=None, bcc=None, path=None):
        """初始化Email用于发送邮件
        :param path: 附件路径，可传入list（多附件）或str（单个附件），非必填。
        :param receiver: 收件人，多收件人用“;”隔开，必填
        :param cc: 抄送人，多收件人用“;”隔开，非必填
        :param bcc: 秘送人，多收件人用“;”隔开，非必填
        """

        self.title = "{} Automation Report".format(datetime.datetime.now().strftime('%Y-%m-%d-%H'))
        self.message = "<html><body><a href='#'>This is an automation run result report email.Please do not reply.</a></body></html>"
        self.files = path

        self.msg = MIMEMultipart('related')

        self.server = SMTP_SERVER
        self.sender = sender[0]
        self.receiver = receiver
        self.password = sender[1]
        self.cc = cc
        self.bcc = bcc

    def _attach_file(self, att_file):
        att = MIMEText(open('%s' % att_file, 'rb').read(), 'plain', 'utf-8')
        att["Content-Type"] = 'application/octet-stream'
        file_name = re.split(r'[\\|/]', att_file)
        att["Content-Disposition"] = 'attachment; filename="%s"' % file_name[-1]
        self.msg.attach(att)

    def send(self):

        self.msg['Subject'] = self.title
        self.msg['From'] = self.sender
        self.msg['To'] = self.receiver
        self.msg['Cc'] = self.cc
        self.msg['Bcc'] = self.bcc

        # 邮件正文
        if self.message:
            self.msg.attach(MIMEText(self.message, 'html'))  # html-html格式  plain-纯文本格式

        # 添加附件，支持多个附件（传入list），或者单个附件（传入str）
        if self.files:
            if isinstance(self.files, list):
                for f in self.files:
                    self._attach_file(f)
            elif isinstance(self.files, str):
                self._attach_file(self.files)

        # 连接服务器并发送
        try:
            # smtplib.SMTP_SSL(host=self.serve, port=25) # 安全连接通道
            smtp_server = smtplib.SMTP(self.server)  # 连接sever
            smtp_server.connect(self.server, 25)
        except (gaierror and error) as e:
            LOG.error('发送邮件失败,无法连接到SMTP服务器，检查网络以及SMTP服务器. %s', e)
            pass
        else:
            try:
                smtp_server.starttls()
                smtp_server.login(user=self.sender, password=self.password)  # 登录
            except smtplib.SMTPAuthenticationError as e:
                LOG.error('用户名密码验证失败！%s', e)
                pass
            else:
                send_rec = self.receiver.split(';')
                if self.cc:
                    if self.bcc:
                        send_rec = self.receiver.split(';') + self.bcc.split(';') + self.cc.split(';')
                    send_rec = self.receiver.split(';') + self.cc.split(';')
                smtp_server.sendmail(self.sender, send_rec, self.msg.as_string())  # 发送邮件
            finally:
                smtp_server.quit()  # 断开连接
                LOG.info('发送邮件"{0}"成功! 收件人：{1}。如果没有收到邮件，请检查垃圾箱,同时检查收件人地址是否正确'.format(self.title, self.receiver))


class Message(object):
    @staticmethod
    def receive():
        """ 创建POP3对象，添加用户名和密码"""
        pop3sever = poplib.POP3(POP3_SERVER)
        pop3sever.user(SENDER[0])
        pop3sever.pass_(SENDER[1])

        """获取邮件请求返回状态码、每封邮件的字节大小(b'第几封邮件 此邮件字节大小')、"""
        response, msg_num_octets, octets = pop3sever.list()

        """ 获取任意一封邮件的邮件对象【第一封邮件的编号为1，而不是0】"""
        response, msg_lines, octets = pop3sever.retr(len(msg_num_octets))
        msg = b"\r\n".join(msg_lines).decode("utf8", "ignore")
        message_object = Parser().parsestr(msg)

        """ 终止POP3服务"""
        pop3sever.quit()
        return message_object


def decode_str(s):
    """
    解析邮件正文
    """
    value, charset = decode_header(s)[0]
    if charset:
        value = value.decode(charset)
    return value


def decode_date(email_time):
    """
    解析邮件时间
    """
    email_date = email_time.split(",")[-1][1:-6]
    # datetime.datetime.now().day
    return email_date


def guess_charset(msg):
    """
    解析邮件头 收件人 抄送人
    """
    charset = msg.get_charset()
    if charset is None:
        content_type = msg.get('Content-Type', '').lower()
        pos = content_type.find('charset=')
        if pos >= 0:
            charset = content_type[pos + 8:].strip()
    return charset


msg_dic = {}


def show_info(msg, indent=0):
    if indent == 0:
        for header in ['From', 'To', 'Subject', 'Date']:
            value = msg.get(header, '')
            if value:
                if header == 'Subject':
                    value = decode_str(value)
                elif header in ["From", "TO"]:
                    hdr, addr = parseaddr(value)
                    name = decode_str(hdr)
                    value = u'%s <%s>' % (name, addr)
                elif header == "Date":
                    value = decode_date(value)
            # print('%s%s: %s' % ('  ' * indent, header, value))
            msg_dic[header] = value
    if msg.is_multipart():
        parts = msg.get_payload()
        for n, part in enumerate(parts):
            # print('%spart %s' % ('  ' * indent, n))
            # print('%s--------------------' % ('  ' * indent))
            show_info(part, indent + 1)
    else:
        content_type = msg.get_content_type()
        if content_type == 'text/plain' or content_type == 'text/html':
            content = msg.get_payload(decode=True)
            charset = guess_charset(msg)
            if charset:
                content = content.decode(charset)
            # print('%sText: %s' % ('  ' * indent, content + '...'))
            msg_dic["Text"] = content
        else:
            # print('%sAttachment: %s' % ('  ' * indent, content_type))
            msg_dic["Attachment"] = content_type
    return msg_dic


if __name__ == '__main__':
    # print(Message().receive())
    print(show_info(Message().receive()))
